/**
 * <copyright>
 * </copyright>
 *
 * $Id$
 */
package org.eclipse.wst.wsdl.internal.impl;


import java.util.Collection; //import java.util.HashMap;
import java.util.Iterator;
import java.util.List; //import java.util.Map;

import javax.wsdl.extensions.ExtensibilityElement;
import javax.xml.namespace.QName;

import org.apache.log4j.Logger;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList; //import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.util.EObjectContainmentEList;
import org.eclipse.emf.ecore.util.EObjectResolvingEList;
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.wst.wsdl.Definition; //import org.eclipse.wst.wsdl.Part;
//import org.eclipse.wst.wsdl.Part;
import org.eclipse.wst.wsdl.Namespace;
import org.eclipse.wst.wsdl.PartnerLinkType;
import org.eclipse.wst.wsdl.Role;
import org.eclipse.wst.wsdl.WSDLElement;
import org.eclipse.wst.wsdl.WSDLPackage;
import org.eclipse.wst.wsdl.internal.util.WSDLUtil;
import org.eclipse.wst.wsdl.util.WSDLConstants;
import org.w3c.dom.Element;
import org.w3c.dom.Node;


/**
 * <!-- begin-user-doc -->
 * An implementation of the model object '<em><b>Partner Link Type</b></em>'.
 * <!-- end-user-doc -->
 * <p>
 * The following features are implemented:
 * <ul>
 *   <li>{@link org.eclipse.wst.wsdl.internal.impl.PartnerLinkTypeImpl#getName <em>Name</em>}</li>
 *   <li>{@link org.eclipse.wst.wsdl.internal.impl.PartnerLinkTypeImpl#getID <em>ID</em>}</li>
 *   <li>{@link org.eclipse.wst.wsdl.internal.impl.PartnerLinkTypeImpl#getRole <em>Role</em>}</li>
 *   <li>{@link org.eclipse.wst.wsdl.internal.impl.PartnerLinkTypeImpl#getQName <em>QName</em>}</li>
 *   <li>{@link org.eclipse.wst.wsdl.internal.impl.PartnerLinkTypeImpl#getEParts <em>EParts</em>}</li>
 * </ul>
 * </p>
 *
 * @generated
 */
public class PartnerLinkTypeImpl extends ExtensibleElementImpl implements PartnerLinkType
{

  private static transient Logger log = Logger.getLogger(PartnerLinkTypeImpl.class);

  /**
   * The default value of the '{@link #getName() <em>Name</em>}' attribute.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @see #getName()
   * @generated
   * @ordered
   */
  protected static final String NAME_EDEFAULT = null;

  /**
   * The cached value of the '{@link #getName() <em>Name</em>}' attribute.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @see #getName()
   * @generated
   * @ordered
   */
  protected String name = NAME_EDEFAULT;

  /**
   * The default value of the '{@link #getID() <em>ID</em>}' attribute.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @see #getID()
   * @generated
   * @ordered
   */
  protected static final String ID_EDEFAULT = null;

  /**
   * The cached value of the '{@link #getID() <em>ID</em>}' attribute.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @see #getID()
   * @generated
   * @ordered
   */
  protected String id = ID_EDEFAULT;

  /**
   * The cached value of the '{@link #getRole() <em>Role</em>}' reference list.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @see #getRole()
   * @generated
   * @ordered
   */
  protected EList role;

  /**
   * The default value of the '{@link #getQName() <em>QName</em>}' attribute.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @see #getQName()
   * @generated
   * @ordered
   */
  protected static final QName QNAME_EDEFAULT = null;

  /**
   * The cached value of the '{@link #getQName() <em>QName</em>}' attribute.
   * <!-- begin-user-doc -->
  	 * <!-- end-user-doc -->
   * @see #getQName()
   * @generated
   * @ordered
   */
  protected QName qName = QNAME_EDEFAULT;

  /**
   * The cached value of the '{@link #getEParts() <em>EParts</em>}' containment reference list.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @see #getEParts()
   * @generated
   * @ordered
   */
  protected EList eParts;

  /**
   * <!-- begin-user-doc -->
       * <!-- end-user-doc -->
   * @generated
   */
  protected PartnerLinkTypeImpl()
  {
    super();
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  protected EClass eStaticClass()
  {
    return WSDLPackage.Literals.PARTNER_LINK_TYPE;
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   
  public String getName()
  {
    return name;
  }*/

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   
  public void setName(String newName)
  {
    log.trace("PartnerLinkTypeImpl name: " + newName);
    String oldName = name;
    name = newName;
    if (eNotificationRequired())
      eNotify(new ENotificationImpl(this, Notification.SET, WSDLPackage.PARTNER_LINK_TYPE__NAME, oldName, name));
  }*/

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public String getID()
  {
    return id;
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public void setID(String newID)
  {
    String oldID = id;
    id = newID;
    if (eNotificationRequired())
      eNotify(new ENotificationImpl(this, Notification.SET, WSDLPackage.PARTNER_LINK_TYPE__ID, oldID, id));
  }

  /**
   * <!-- begin-user-doc -->
   * Get all the parts defined here.
   * <!-- end-user-doc -->
   * @generated NOT
   */
  public EList getRole()
  {
    EList hashMap = new BasicEList();
    for (Iterator i = getEParts().iterator(); i.hasNext();)
    {
      Role roleInstance = (Role)i.next();
      hashMap.add(roleInstance);
    }
    return hashMap;
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public EList getRoleGen()
  {
    if (role == null)
    {
      role = new EObjectResolvingEList(Role.class, this, WSDLPackage.PARTNER_LINK_TYPE__ROLE);
    }
    return role;
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public QName getQName()
  {
    return qName;
  }

  /**
   * <!-- begin-user-doc -->
  	 * <!-- end-user-doc -->
   * @generated
   */
  public void setQName(QName newQName)
  {
//    log.trace("PartnerLinkTypeImpl name: " + newQName);
    QName oldQName = qName;
    qName = newQName;
    if (eNotificationRequired())
      eNotify(new ENotificationImpl(this, Notification.SET, WSDLPackage.PARTNER_LINK_TYPE__QNAME, oldQName, qName));
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public EList getEParts()
  {
    if (eParts == null)
    {
      eParts = new EObjectContainmentEList(Role.class, this, WSDLPackage.PARTNER_LINK_TYPE__EPARTS);
    }
    return eParts;
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs)
  {
    switch (featureID)
    {
      case WSDLPackage.PARTNER_LINK_TYPE__EPARTS:
      return ((InternalEList)getEParts()).basicRemove(otherEnd, msgs);
    }
    return super.eInverseRemove(otherEnd, featureID, msgs);
  }

  /**
   * <!-- begin-user-doc -->
       * <!-- end-user-doc -->
   * @generated
   */
  public Object eGet(int featureID, boolean resolve, boolean coreType)
  {
    switch (featureID)
    {
      case WSDLPackage.PARTNER_LINK_TYPE__NAME:
//        return getName();
        throw new Error("NotImplementedException");
      case WSDLPackage.PARTNER_LINK_TYPE__ID:
      return getID();
      case WSDLPackage.PARTNER_LINK_TYPE__ROLE:
      return getRole();
      case WSDLPackage.PARTNER_LINK_TYPE__QNAME:
      return getQName();
      case WSDLPackage.PARTNER_LINK_TYPE__EPARTS:
      return getEParts();
    }
    return super.eGet(featureID, resolve, coreType);
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public void eSet(int featureID, Object newValue)
  {
    switch (featureID)
    {
      case WSDLPackage.PARTNER_LINK_TYPE__NAME:
//        setName((String)newValue);
//        return;
        throw new Error("Not Implemented Exception");
      
      case WSDLPackage.PARTNER_LINK_TYPE__ID:
      setID((String)newValue);
      return;
      case WSDLPackage.PARTNER_LINK_TYPE__ROLE:
      getRole().clear();
      getRole().addAll((Collection)newValue);
      return;
      case WSDLPackage.PARTNER_LINK_TYPE__QNAME:
      setQName((QName)newValue);
      return;
      case WSDLPackage.PARTNER_LINK_TYPE__EPARTS:
      getEParts().clear();
      getEParts().addAll((Collection)newValue);
      return;
    }
    super.eSet(featureID, newValue);
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public void eUnset(int featureID)
  {
    switch (featureID)
    {
      case WSDLPackage.PARTNER_LINK_TYPE__NAME:
//      setName(NAME_EDEFAULT);
//      return;
        throw new Error("NotImplementedException");
      case WSDLPackage.PARTNER_LINK_TYPE__ID:
      setID(ID_EDEFAULT);
      return;
      case WSDLPackage.PARTNER_LINK_TYPE__ROLE:
      getRole().clear();
      return;
      case WSDLPackage.PARTNER_LINK_TYPE__QNAME:
      setQName(QNAME_EDEFAULT);
      return;
      case WSDLPackage.PARTNER_LINK_TYPE__EPARTS:
      getEParts().clear();
      return;
    }
    super.eUnset(featureID);
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public boolean eIsSet(int featureID)
  {
    switch (featureID)
    {
      case WSDLPackage.PARTNER_LINK_TYPE__NAME:
      return NAME_EDEFAULT == null ? name != null : !NAME_EDEFAULT.equals(name);
      case WSDLPackage.PARTNER_LINK_TYPE__ID:
      return ID_EDEFAULT == null ? id != null : !ID_EDEFAULT.equals(id);
      case WSDLPackage.PARTNER_LINK_TYPE__ROLE:
      return role != null && !role.isEmpty();
      case WSDLPackage.PARTNER_LINK_TYPE__QNAME:
      return QNAME_EDEFAULT == null ? qName != null : !QNAME_EDEFAULT.equals(qName);
      case WSDLPackage.PARTNER_LINK_TYPE__EPARTS:
      return eParts != null && !eParts.isEmpty();
    }
    return super.eIsSet(featureID);
  }

  /**
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @generated
   */
  public String toString()
  {
    if (eIsProxy())
      return super.toString();

    StringBuffer result = new StringBuffer(super.toString());
    result.append(" (name: "); //$NON-NLS-1$
    result.append(name);
    result.append(", ID: "); //$NON-NLS-1$
    result.append(id);
    result.append(", qName: "); //$NON-NLS-1$
    result.append(qName);
    result.append(')');
    return result.toString();
  }

  //
  // For reconciliation: Model -> DOM
  //

  //  protected void changeAttribute(EAttribute eAttribute)
  //  {
  //    if (isReconciling)
  //      return;
  //
  //    super.changeAttribute(eAttribute);
  //    Element theElement = getElement();
  //    if (theElement != null)
  //    {
  //      if (eAttribute == null || eAttribute == WSDLPackage.Literals.SERVICE__QNAME)
  //        niceSetAttribute(theElement, WSDLConstants.NAME_ATTRIBUTE, getQName().getLocalPart());
  //    }
  //  }

  //
  // Reconcile methods
  //

  public void reconcileAttributes(Element changedElement)
  {
    Definition definition = getEnclosingDefinition();
    String name = changedElement.getAttribute(WSDLConstants.NAME_ATTRIBUTE);
    QName qname = new QName(definition.getTargetNamespace(), name == null ? "" : name); //$NON-NLS-1$
    setQName(qname);
  }

  /**
   * wb: This method is called for the subelements of the PartnerLinkType element
   */
  public void handleUnreconciledElement(Element child, Collection remainingModelObjects)
  {
    //    log.trace("handleUnreconciledElement() - child: " + child + " WSDLType: "
    //      + WSDLConstants.getElementTag(WSDLUtil.getInstance().getWSDLType(child)));

    switch (WSDLUtil.getInstance().getWSDLType(child))
    {

      //      case WSDLConstants.PART:
      //      Part part = ((WSDLPackage)EPackage.Registry.INSTANCE.getEPackage(WSDLPackage.eNS_URI)).getWSDLFactory().createPart();
      //      part.setEnclosingDefinition(getEnclosingDefinition());
      //      part.setElement(child);
      //      //        getEParts().add(part);
      //        break;

      case WSDLConstants.ROLE:
      Role role = ((WSDLPackage)EPackage.Registry.INSTANCE.getEPackage(WSDLPackage.eNS_URI)).getWSDLFactory().createRole();
      role.setEnclosingDefinition(getEnclosingDefinition());
      role.setElement(child);

      getEParts().add(role);

        break;

      default:
      super.handleUnreconciledElement(child, remainingModelObjects);
        break;
    }
  }

  protected void adoptContent(EReference eReference, Object object)
  {
    if (object instanceof WSDLElement)
    {
      WSDLElement wsdlElement = (WSDLElement)object;
      if (isReconciling)
      {
        if (wsdlElement.getElement() != null)
        {
          ((WSDLElementImpl)wsdlElement).elementChanged(wsdlElement.getElement());
        }
      }
      else
      {
        Element childElement = wsdlElement.getElement();
        if (getElement() != null && (childElement == null || childElement.getParentNode() == null))
        {
          if (childElement != null && childElement.getOwnerDocument() != getElement().getOwnerDocument())
          {
            wsdlElement.setElement(null);
            childElement = null;
          }

          handleElementForAdopt(eReference, wsdlElement);
          ((WSDLElementImpl)wsdlElement).updateElement();
        }
      }

      Definition definition = getEnclosingDefinition();
      if (definition != null)
      {
        ((WSDLElementImpl)wsdlElement).adoptBy(definition);
      }
    }
    else if (object instanceof Namespace)
    {
      // Add a namespace attribute to the Definitions element.
      Namespace ns = (Namespace)object;
      Node adoptionParent = getAdoptionParentNode(eReference); // Definitions node
      // KB: Assumption - The prefix is unique if we are here (by the Definitions model). 
      if (adoptionParent != null)
      {
        ((Element)adoptionParent).setAttribute("xmlns:" + ns.getPrefix(), ns.getURI());
      }
    }
  }

  public ExtensibilityElement removeExtensibilityElement(ExtensibilityElement extElement)
  {
    // TODO Auto-generated method stub
    return null;
  }

} //PartnerLinkTypeImpl
